package Myfun;

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.TimerTask;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 周斌
 * Date: 2024-06-25
 * Time: 15:22
 */
//1.定义一个TimeTask类表示一个任务，这个类中需要任务执行的时间和描述任务。
class TimeTask implements Comparable<TimeTask> {
    public Runnable runnable;
    //此时的time不是程序等待的时间，而是一个绝对时间
    public long time;
    public TimeTask(Runnable runnable,long delay) {
        this.runnable = runnable;
        //手动换算时间，加一个时间戳将相对时间换算成绝对时间
        this.time = System.currentTimeMillis() + delay;
    }
    public void run() {
        runnable.run();
    }
    public long getTime() {
        return time;
    }
    @Override
    public int compareTo(TimeTask o) {
        return (int) (this.time - o.time);
    }
}
//2.定义一个数据结构来管理多个任务，此处我们优先级队列来管理多个任务，因为用其他的数据结构去管理的话，
// 就需要不断去扫描数据结构中满足要求的成员，遇到数据量庞大的那么开销就巨大，得不偿失，
// 用优先级队列可以避免这种情况，由于要求等待时间短的先运行，那么我们可以定义一个小根堆。
class MyTime{
    Object locker = new Object();
    public PriorityQueue<TimeTask> queue = new PriorityQueue<>();
    //初始化线程，并且调用任务
    public MyTime() {
        //定义一个扫描线程来获取堆顶任务
        Thread t = new Thread(()-> {
            try {
                while(true) {
                    synchronized (locker) {
                        if (queue.size() == 0) {
                            locker.wait();
                        }
                    //取小堆中堆顶的任务
                    TimeTask task = queue.peek();
                    //获取当前的时间戳
                    long curTime = System.currentTimeMillis();
                    //看任务的时间是否到了
                    if(curTime >= task.getTime()) {
                        //时间到了，则执行任务
                        task.run();
                        //任务执行完之后，则将队列中的堆顶任务消除
                        queue.poll();
                    } else {
                        //任务时间没到，则堵塞,阻塞多久？堵塞任务等待的时间
                            locker.wait(task.getTime() - curTime);
                        }
                    }
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        t.start();
    }
    //提供一个schedule方法来创建任务
    public void schedule(Runnable runnable,long delay) {
        synchronized (locker) {
            TimeTask timeTask = new TimeTask(runnable,delay);
            queue.offer(timeTask);
            //唤醒调用任务的线程
            locker.notify();
        }
    }
}
public class MyTimerTest {
    public static void main(String[] args) {
        MyTime myTime = new MyTime();
        myTime.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello,1000");
            }
        },1000);

        myTime.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello,2000");
            }
        },2000);
        myTime.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello,3000");
            }
        },3000);
    }
}
